#pragma once 
#include "Reactor.hpp"
#include "Socket.hpp"
#include "InetAddr.hpp"
#include "Connection.hpp"
#include "Log.hpp"

class Channel:public Connection{
const static int size = 1024;
	public:
	Channel(int sockfd, InetAddr client):_sockfd(sockfd), _client_addr(client){
		SetNoBlock(_sockfd);
		SetEvents(EPOLLIN | EPOLLET);
	}

	void Recever() override{
		char buffer[size];
		while(true){
			int recv_ret = recv(_sockfd, buffer, sizeof(buffer)-1, 0);
			if(recv_ret > 0){
				buffer[recv_ret] = 0;
				_inbuffer += buffer;

				// 调用业务回调处理数据
				std::string resp = _handler(_inbuffer);

				if(!resp.empty()){
					_outbuffer += resp;
					Sender();
				}
			}
			else if(recv_ret == 0){
				LOG(LogLevel::ERROR) << "client closed";
				Excepter();
				break;
			}
			else{
				if(errno == EAGAIN || errno == EWOULDBLOCK){
					// 非阻塞状态，无数据可读
					LOG(LogLevel::DEBUG) << "no data available for reading";
					break;
				}
				else if(errno == EINTR){
					// 信号中断，继续接收数据
					continue;
				}
				else{
					LOG(LogLevel::ERROR) << "recv error: " << strerror(errno);
					Excepter();
					break;
				}
			}
		}
	}

	void Sender() override{
		if(_outbuffer.empty())
			return;

		while(true){
			int send_ret = send(_sockfd, _outbuffer.c_str(), _outbuffer.size(), 0);
			if(send_ret > 0){
				_outbuffer.erase(0, send_ret);
				if(_outbuffer.empty())
					break;
			}
			else if(send_ret == 0)
				break;
			else{
				if(errno == EAGAIN || errno == EWOULDBLOCK)
					break;
				else if(errno == EINTR)
					continue;
				else{
					Excepter();
					break;
				}
					
			}

			if(!_outbuffer.empty()){
				GetOwner()->EnableReadWrite(_sockfd, true, true);
			}
			else{
				GetOwner()->EnableReadWrite(_sockfd, true, false);
			}
		}
	}

	void Excepter() override{
		GetOwner()->DelConnection(_sockfd);
	}

	int GetSockFd() override{
		return _sockfd;
	}

	std::string& GetInBuffer(){
		return _inbuffer;
	}

	void AppendOutBuffer(const std::string& msg){
		_outbuffer += msg;
		if(!_outbuffer.empty()){
			Sender();
		}
	}

	~Channel(){
		if(_sockfd >= 0){
			close(_sockfd);
			_sockfd = -1;
		}
		LOG(LogLevel::DEBUG) << "~Channel()";
	}


private:
	int _sockfd;
	InetAddr _client_addr;
	std::string _inbuffer; // 读缓冲区
	std::string _outbuffer; // 写缓冲区
};